package kr.pe.johnkim.pushchat.mobile.service;

import kr.pe.johnkim.pushchat.mobile.dao.PushChatMemberDao;
import kr.pe.johnkim.pushchat.mobile.domain.PushChatMember;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;

/**
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 6. 12.
 */
@Service
public class PushChatMemberServiceImpl implements PushChatMemberService {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(PushChatMemberServiceImpl.class);

    @Autowired
    private PushChatMemberDao pushChatMemberDao;

    // 생성 할 프로필 썸네일 가로 크기.
    private @Value("${profile.thumbnail.width}") int profileThumbnailWidth;

    // 생성 할 프로필 썸네일 세로 크기.
    private @Value("${profile.thumbnail.height}") int profileThumbnailHeight;

    /**
     * 멤버 아이디 중복 확인을 한다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public PushChatMember selectDuplicationMember(PushChatMember pushChatMember) {
        logger.info("selectDuplicationMember");
        return this.pushChatMemberDao.selectDuplicationMember(pushChatMember);
    }

    /**
     * 멤버를 등록 한다.
     *
     * @param pushChatMember
     */
    @Override
    public void registerMember(PushChatMember pushChatMember) {
        logger.info("registerMember");
        this.pushChatMemberDao.registerMember(pushChatMember);
    }

    /**
     * 멤버 로그인을 한다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public PushChatMember login(PushChatMember pushChatMember) {
        logger.info("login");
        return this.pushChatMemberDao.login(pushChatMember);
    }

    /**
     * 멤버 목록을 가져 온다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public List<PushChatMember> selectMemberList(PushChatMember pushChatMember) {
        logger.info("selectMemberList");
        return this.pushChatMemberDao.selectMemberList(pushChatMember);
    }

    /**
     * 사용자의 GCM / APNS Device Token 을 업데이트 한다.
     *
     * @param pushChatMember
     */
    @Override
    public void updateRegistrationId(PushChatMember pushChatMember) {
        logger.info("updateRegistrationId");
        this.pushChatMemberDao.updateRegistrationId(pushChatMember);
    }

    /**
     * 멤버 정보를 가져 온다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public PushChatMember selectMemberInformation(PushChatMember pushChatMember) {
        logger.info("selectMemberInformation");
        return this.pushChatMemberDao.selectMemberInformation(pushChatMember);
    }

    /**
     * 멤버를 검색 한다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public List<PushChatMember> selectSearchMemberList(PushChatMember pushChatMember) {
        logger.info("selectSearchMemberList");
        return this.pushChatMemberDao.selectSearchMemberList(pushChatMember);
    }

    /**
     * 비밀 번호를 수정 한다.
     *
     * @param pushChatMember
     */
    @Override
    public void updatePassword(PushChatMember pushChatMember) {
        logger.info("updatePassword");
        this.pushChatMemberDao.updatePassword(pushChatMember);
    }

    /**
     * 멤버 일반 정보를 수정 한다.
     *
     * @param pushChatMember
     */
    @Override
    public void updateMemberInformation(PushChatMember pushChatMember) {
        logger.info("updateMemberInformation");
        this.pushChatMemberDao.updateMemberInformation(pushChatMember);
    }

    /**
     * 멤버 일반 정보와 프로필 이미지를 같이 수정 한다.
     *
     * @param pushChatMember
     */
    @Override
    public void updateMemberInformationWithProfileImage(PushChatMember pushChatMember, String uploadProfileImagePath, String uploadProfileThumbnailPath, MultipartFile file) {
        logger.info("updateMemberInformationWithProfileImage");

        // 이미지 파일명.
        String fileName = file.getOriginalFilename();

        // 프로필 이미지를 업로드 한다.
        try {
            InputStream inputStream = file.getInputStream();
            OutputStream outputStream = new FileOutputStream(uploadProfileImagePath + fileName);

            int bytesRead;

            byte[] buffer = new byte[8192];

            while((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 프로필 썸네일을 생성 한다.
        try {
            // 썸네일 크기를 설정 한다.
            int width = profileThumbnailWidth;
            int height = profileThumbnailHeight;

            // 원본 이미지 파일을 가져 온다.
            File src = new File(uploadProfileImagePath + fileName);

            BufferedImage bufferedImage = ImageIO.read(src);

            // Aspect Ratio 를 유지하기 위해서 크기를 조정 한다.
            if((float)width/bufferedImage.getWidth() > (float)height/bufferedImage.getHeight()) {
                width = (int)(bufferedImage.getWidth() * ((float)height/bufferedImage.getHeight()));
            } else {
                height = (int)(bufferedImage.getHeight() * ((float)width/bufferedImage.getWidth()));
            }

            BufferedImage thImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics2D = thImg.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.drawImage(bufferedImage, 0, 0, width, height, null);
            graphics2D.dispose();

            File destinationFile = new File(uploadProfileThumbnailPath + fileName);
            ImageIO.write(thImg, "png", destinationFile);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 멤버 정보를 수정 한다.
        this.pushChatMemberDao.updateMemberInformation(pushChatMember);
    }

    /**
     * 닉네임 중복 확인을 한다.
     *
     * @param pushChatMember
     * @return
     */
    @Override
    public PushChatMember selectDuplicationNickName(PushChatMember pushChatMember) {
        logger.info("selectDuplicationNickName");
        return this.pushChatMemberDao.selectDuplicationNickName(pushChatMember);
    }
}
